﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MacomberMapSystem.Common.CIM;
using System.Xml;
using MacomberMapSystem.Common.Database;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;

namespace MacomberMapSystem.Common.Processing
{
    /// <summary>
    /// This class holds information on a CIM procesor delta
    /// </summary>
    public class CIM_Processor_Delta
    {
        #region Variable declarations
        /// <summary>The class type creating the log</summary>
        public Type Sender;

        /// <summary>
        /// The delta type included
        /// </summary>
        [Flags]
        public enum enumDeltaType
        {
            /// <summary>New equipment added</summary>
            Addition = 1,
            /// <summary>Equipment removed</summary>
            Removal = 2,
            /// <summary>Topology has changed</summary>
            TopologyChange=4,
            /// <summary>A resource node has been added</summary>
            ResourceNodeAdd=8,
            /// <summary>A resource node has been removed</summary>
            ResourceNodeRemove=16,
            /// <summary>A one-line has changed for aesthetic reasons</summary>
            OneLineChange=32,
            /// <summary>Ownership has changed</summary>
            OwnerChanged=64,
            /// <summary>Operatorship has changed</summary>
            OperatorChanged=128,
            /// <summary>Ratings have changed</summary>
            RatingsChanged=256,
            /// <summary>Names (short or long) have changed</summary>
            NameChanges=512
        }

        /// <summary>The delta type</summary>
        public enumDeltaType DeltaType;

        /// <summary>The parent of the change</summary>
        public CIM_Element Parent;

        /// <summary>The rdf:ID of the child</summary>
        public CIM_RdfID Child;

        /// <summary>The object (if any) of the prior state</summary>
        public object BeforeObject = null;

        /// <summary>The object (if any) of the new state</summary>
        public object AfterObject = null;
        #endregion

        #region Initialization
        /// <summary>
        /// Initialize a new delta
        /// </summary>
        /// <param name="Sender"></param>
        /// <param name="DeltaType"></param>
        /// <param name="Parent"></param>
        /// <param name="Child"></param>
        public CIM_Processor_Delta(Type Sender, enumDeltaType DeltaType, CIM_Element Parent, CIM_RdfID Child)
        {
            this.Sender = Sender;
            this.DeltaType = DeltaType;
            this.Parent = Parent;
            this.Child = Child;
        }
        #endregion

        #region Export
        /// <summary>
        /// Write out our change
        /// </summary>
        /// <param name="xW"></param>
        /// <param name="Model"></param>
        public void Export(XmlTextWriter xW, MM_Database_Model Model)
        {
            xW.WriteStartElement("Delta");
            foreach (enumDeltaType DeltaType in Enum.GetValues(typeof(enumDeltaType)))
                if ((DeltaType & this.DeltaType) == DeltaType)
                    xW.WriteAttributeString(Enum.GetName(typeof(enumDeltaType), DeltaType), "true");
            
            CIM_Element Elem = Model.FromRdfID(Child);
            if (Elem == null && Model.PriorModel != null && Model.PriorModel.State == MM_Database_Model.enumModelState.Completed)
                Elem = Model.PriorModel.FromRdfID(Child);
            
            
            WriteElem(xW, "Parent", Parent, Parent.rdfID);            
            WriteElem(xW, "Child", Elem, Child);
            WriteObject(xW, "Before", BeforeObject);
            WriteObject(xW, "After", BeforeObject);                                               
            xW.WriteEndElement();
        }

        /// <summary>
        /// Write out an object
        /// </summary>
        /// <param name="xW"></param>
        /// <param name="Name"></param>
        /// <param name="ExportObject"></param>
        private void WriteObject(XmlTextWriter xW, String Name, Object ExportObject)
        {
            if (ExportObject == null)
                return;
            else if (ExportObject is Bitmap)
                using (MemoryStream mS = new MemoryStream())
                {
                    (ExportObject as Bitmap).Save(mS, ImageFormat.Png);
                    xW.WriteElementString(Name, Convert.ToBase64String(mS.ToArray()));
                }

        }

        /// <summary>
        /// Return the bytes associated with an image.
        /// </summary>
        /// <param name="InBitmap"></param>
        /// <returns></returns>
        private string GetBitmapBytes(Bitmap InBitmap)
        {
            if (InBitmap == null)
                return "";
            else
                using (MemoryStream OutStream = new MemoryStream())
                {
                    InBitmap.Save(OutStream, ImageFormat.Png);
                    return Convert.ToBase64String(OutStream.ToArray());
                }
        }

        private void WriteElem(XmlTextWriter  xW, String Title, CIM_Element Elem, CIM_RdfID rdfID)
        {
            xW.WriteStartElement(Title);
            xW.WriteAttributeString("rdfID", rdfID.ToString());
            if (Elem != null)
            {
                xW.WriteAttributeString("Type", Elem.ElemType);
                xW.WriteAttributeString("Name", Elem.Name);
                xW.WriteAttributeString("Description", Elem.LongName);
                if (!String.IsNullOrEmpty(Parent.TEID))
                    xW.WriteAttributeString("TEID", Elem.TEID.ToString());
            }
            xW.WriteEndElement();            
        }
        #endregion
    }
}
